// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Game1.cs" company="">
//   
// </copyright>
// <summary>
//   This is the main type for your game
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace RescueRaiders
{
    using System;
    using System.Diagnostics;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;

    using RescueRaiders.Models;
    using RescueRaiders.Properties;
    using RescueRaiders.Particles;

    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public sealed class Game1 : Game
    {
        // The background will show 500 pixels more in each direction

        // The flyable level is in a rectangle between (500, 0) and (4000, 570)
        /// <summary>
        /// The ground height.
        /// </summary>
        private static readonly int groundHeight = Settings.Default.ViewHeight - Settings.Default.RadarHeight -
                                                   (int)(Math.Pow(Settings.Default.ViewHeight, 2) / 12000);

        /// <summary>
        /// The level.
        /// </summary>
        internal static readonly Rectangle Level = new Rectangle(
            Settings.Default.ViewWidth / 2,
            Settings.Default.RadarHeight,
            Settings.Default.LevelWidth - Settings.Default.ViewWidth,
            groundHeight);

        /// <summary>
        /// The radar height.
        /// </summary>
        private static readonly int radarHeight = Settings.Default.ViewHeight / Settings.Default.RadarHeight;

        /// <summary>
        /// The audio engine.
        /// </summary>
        private AudioEngine audioEngine;

        /// <summary>
        /// The background 1.
        /// </summary>
        private Texture2D background1;

        /// <summary>
        /// The background 2.
        /// </summary>
        private Texture2D background2;

        /// <summary>
        /// The background 3.
        /// </summary>
        private Texture2D background3;

        /// <summary>
        /// The background 4.
        /// </summary>
        private Texture2D background4;

        /// <summary>
        /// The bg pos.
        /// </summary>
        private Vector2 bgPos;

        /// <summary>
        /// The camera x.
        /// </summary>
        private float cameraX;

        /// <summary>
        /// The font.
        /// </summary>
        private SpriteFont font;

        /// <summary>
        /// The helicopter.
        /// </summary>
        private HeliClass helicopter;

        /// <summary>
        /// The heli cue.
        /// </summary>
        private Cue heliCue;

        /// <summary>
        /// The radar.
        /// </summary>
        private Texture2D radar;

        /// <summary>
        /// The sprite batch.
        /// </summary>
        private SpriteBatch spriteBatch;

        /// <summary>
        /// The view port rectangle.
        /// </summary>
        private Rectangle viewPortRectangle;

        // ReSharper disable UnaccessedField.Local
        /// <summary>
        /// The wave bank.
        /// </summary>
        private WaveBank waveBank;

        // ReSharper restore UnaccessedField.Local
        /// <summary>
        /// The x fix.
        /// </summary>
        private float xFix;

        // add this
        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch ; }
        }
        ParticleSystem explosion;
        ParticleSystem smoke;
        ParticleSystem plume;
        ParticleSystem dust;

        // add this

        /// <summary>
        /// Initializes a new instance of the <see cref="Game1"/> class.
        /// </summary>
        internal Game1()
        {
            new GraphicsDeviceManager(this)
                {
                    PreferredBackBufferWidth = Settings.Default.ViewWidth,
                    PreferredBackBufferHeight = Settings.Default.ViewHeight,
                    IsFullScreen = false
                };
            Content.RootDirectory = "Content";

            // add this
            explosion = new ExplosionParticleSystem(this,Properties.Settings.Default.NumberOfEachEffect, "Sprites\\explosion");
            smoke = new ExplosionSmokeParticleSystem(this, Properties.Settings.Default.NumberOfEachEffect, "Sprites\\smoke");
            plume = new PlumeParticleSystem(this, Properties.Settings.Default.NumberOfEachEffect, "Sprites\\smoke");
            dust = new DustParticleSystem(this, Properties.Settings.Default.NumberOfEachEffect, "Sprites\\dust");
            Components.Add(explosion);
            Components.Add(smoke);
            Components.Add(plume);
            Components.Add(dust);
            // add this
        }

        /// <summary>
        /// Gets Listener.
        /// </summary>
        internal static AudioListener Listener { get; private set; }

        /// <summary>
        /// Gets SoundBank.
        /// </summary>
        internal static SoundBank SoundBank { get; private set; }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">
        /// Provides a snapshot of timing values.
        /// </param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.AliceBlue);
            xFix = helicopter.CameraFix * viewPortRectangle.Center.X * 0.7f;
            cameraX = helicopter.Position.X - viewPortRectangle.Center.X + xFix;
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);
            
            // drawing the backgrounds
            DrawParallax();

            // Draw all the models
            ModelFactory.Instance.Draw(spriteBatch, cameraX, radar);

            // 3d sound changes
            helicopter.Emitter.Position = new Vector3(-xFix, helicopter.Position.Y, 0);
            heliCue.Apply3D(Listener, helicopter.Emitter);

            // temporary details
            WriteInfo();
            spriteBatch.End();
            base.Draw(gameTime);
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            viewPortRectangle = GraphicsDevice.Viewport.TitleSafeArea;
            cameraX = Level.Width;

            // loading the sound
            audioEngine = new AudioEngine(@"content\Sound\RescueRaidersAudio.xgs");
            waveBank = new WaveBank(audioEngine, @"content\Sound\Wave Bank.xwb");
            SoundBank = new SoundBank(audioEngine, @"content\Sound\Sound Bank.xsb");
            Listener = new AudioListener();

            // Create a new SpriteBatch, which can be used to draw textures
            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>(@"fonts\\SpriteFont1");
            background1 = Content.Load<Texture2D>(@"BackGround\BackGround1");
            background2 = Content.Load<Texture2D>(@"BackGround\BackGround2");
            background3 = Content.Load<Texture2D>(@"BackGround\BackGround3");
            background4 = Content.Load<Texture2D>(@"BackGround\BackGround4");
            radar = Content.Load<Texture2D>(@"Sprites\radar");



            // create helicopter
            var position = new Vector2(Level.Width * 0.5f, Level.Height * 0.7f);
            helicopter = ModelFactory.Instance.CreateHelicopter(
                Content.Load<Texture2D>(@"Sprites\helicopter"), position, Side.Player1);

            // create aaGun
            var bulletTexture = Content.Load<Texture2D>(@"Sprites\bullets");
            var gunTexture = Content.Load<Texture2D>(@"Sprites\AA gun");
            position.Y = Level.Bottom - (gunTexture.Height / 2f);
            for (var i = 0; i < 1; i++)
            {
                position.X += 450;
                ModelFactory.Instance.CreateAAGun(gunTexture, bulletTexture, position, Side.Player2);
            }

            // create helipads
            var helipadTexture = Content.Load<Texture2D>(@"Sprites\helipad");
            position.Y = Level.Bottom - (helipadTexture.Height/2)-(helicopter.frameSize.Y/2);
            position.X = Properties.Settings.Default.LevelWidth - Properties.Settings.Default.ViewWidth;
            ModelFactory.Instance.CreateHelipad(helipadTexture, position, Side.Player1);
            position.X = Properties.Settings.Default.ViewWidth;
            ModelFactory.Instance.CreateHelipad(helipadTexture, position, Side.Player2);

            // playing cues
            heliCue = SoundBank.GetCue("heli");
            heliCue.Apply3D(Listener, helicopter.Emitter);
            heliCue.Play();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            Content.Unload();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">
        /// Provides a snapshot of timing values.
        /// </param>
        protected override void Update (GameTime gameTime)
        {
            // Allows the game to exit
            
            audioEngine.Update();
            explosion.Updatecamerax(cameraX);
            smoke.Updatecamerax(cameraX);
            plume.Updatecamerax(cameraX);
            dust.Updatecamerax(cameraX);
            var state = Keyboard.GetState();
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || state.IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            ModelFactory.Instance.Update(this ,gameTime);
            base.Update(gameTime);
        }

        /// <summary>
        /// The draw parallax.
        /// </summary>
        private void DrawParallax()
        {
            spriteBatch.Draw(
                background1, viewPortRectangle, null, Color.White, 0.0f, new Vector2(0, 0), SpriteEffects.None, 1f);
            var f = helicopter.Position.X + xFix;
            bgPos.X = f % background2.Width;
            spriteBatch.Draw(background2, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.9f);
            bgPos.X = bgPos.X - background2.Width;
            spriteBatch.Draw(background2, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.9f);
            bgPos.X = f % background3.Width;
            spriteBatch.Draw(background3, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.8f);
            bgPos.X = bgPos.X - background3.Width;
            spriteBatch.Draw(background3, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.8f);
            bgPos.X = f % Settings.Default.ViewWidth;
            spriteBatch.Draw(background4, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.7f);
            bgPos.X = bgPos.X - background4.Width;
            spriteBatch.Draw(background4, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.7f);
            bgPos.X = bgPos.X - background4.Width;
            spriteBatch.Draw(background4, viewPortRectangle, null, Color.White, 0.0f, bgPos, SpriteEffects.None, 0.7f);
        }

        public void Addparticle(Vector2 collisionPosition, int model1width, int model2width)
        {
            var scale = (float) model2width / model1width ;
            if (scale < .5f) {
                scale = 0.5f; }
            var CollisionPosition = new Vector2(Properties.Settings.Default.ViewWidth/2 -helicopter.Position.X  + collisionPosition.X -xFix, collisionPosition.Y);
            smoke.AddParticles(CollisionPosition, Vector2.Zero, scale);
            explosion.AddParticles(CollisionPosition, Vector2.Zero, scale);
            heliCue = SoundBank.GetCue("explosion");
            heliCue.Apply3D(Listener, helicopter.Emitter);
            heliCue.Play();
        }

        /// <summary>
        /// The write info.
        /// </summary>
        [Conditional("DEBUG")]
        private void WriteInfo()
        {
            spriteBatch.DrawString(
                font,
                "heli posrect" + helicopter.PosRectangle,
                new Vector2(0.02f * viewPortRectangle.Width, 0.05f * viewPortRectangle.Height),
                Color.Black);

            // spriteBatch.DrawString(font, "hits:" + hits,
            // new Vector2(0.02f * viewPortRectangle.Width, 0.15f * viewPortRectangle.Height), Color.Black);
        }
    }
}